//
// Copyright (c) 2005 BroadVision, Inc. All rights reserved.
//
// This software is copyrighted.  Under the copyright laws, this software
// may not be copied, in whole or in part, without prior written consent
// of BroadVision, Inc. or its assignees.  This software is provided under
// the terms of a license between BroadVision and the recipient, and its
// use is subject to the terms of that license.
//
// This software may be protected by one or more U.S. and International
// patents.  Certain applications of BroadVision One-To-One software are
// covered by U.S. patent 5,710,887.
//
// TRADEMARKS: BroadVision and BroadVision One-To-One are registered
// trademarks of BroadVision, Inc., in the United States and the European
// Community, and are trademarks of BroadVision, Inc., in other
// countries.  The BroadVision logo, is a trademark of BroadVision, Inc.,
// in the United States and other countries. Additionally, IONA and Orbix
// are trademarks of IONA Technologies, Ltd.  RSA, MD5, and RC2 are
// trademarks of RSA Data Security, Inc.
//

package com.broadvision.manage.common.tools.action.group;

import java.util.*;
import java.security.Principal;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.Globals;

import com.broadvision.data.client.DataManager;
import com.broadvision.web.util.ViewDynaBean;
import com.broadvision.system.accesscontrol.client.*;
import com.broadvision.visitor.client.VisitorManager;
import com.broadvision.visitor.client.Visitor;
import com.broadvision.visitor.client.VisitorContext;
import com.broadvision.visitor.client.VisitorGroupManager;
import com.broadvision.visitor.interfaces.*;
import com.broadvision.visitor.utils.GroupContextParser;

import com.broadvision.manage.tools.action.BaseAction;
import com.broadvision.manage.common.tools.action.user.UserUtils;
import com.broadvision.portal.services.*;

/**
 * Browses a group.
 */
public class GroupViewAction extends BaseAction {

  public static final String VIEW_BEAN_NAME = "mtGroupView";
  public static final String DTO_BEAN_NAME  = "mtGroupDTO";
  public static final String DTO_MEMBER_BEAN_NAME  = "mtGroupMemberDTO";

  public static final VisitorManager visitorMgr = new VisitorManager();

  /**
   * Implements the action for browsing a group.
   * <p> <p>
   * @param mapping <code>ActionMapping</code> object used to select this instance
   * @param form Optional <code>ActionForm</code> bean for this request (if any)
   * @param request <code>HttpServletRequest</code> object to process
   * @param response <code>HttpServletResponse</code> object to process
   * <p> <p>
   * @return <code>ActionForward</code> instance describing where and how
   * control should be forwarded, or null if the response has already been completed
   * <p> <p>
   * @throws Exception if an error occurs
   */
  public ActionForward processExecute(ActionMapping mapping,
                                      ActionForm form,
                                      HttpServletRequest request,
                                      HttpServletResponse response)
                               throws Exception
  {
    try {
      if (null != request.getAttribute("_groupFQN")) {
        UserUtils.setP(form, "groupFQN", request.getAttribute("_groupFQN"));
      }
      PortalVisitor agent = getPortalVisitor(request);
      Visitor visitor = agent.getVisitor();

      // Retrieve serviceName
      VisitorContext vc = agent.getContext();
      int serviceId = vc.getServiceId();
      String serviceName = DataManager.getServiceName(serviceId);

      String groupFQN = (String) UserUtils.getP(form, "groupFQN");
      ViewDynaBean view = new ViewDynaBean(VIEW_BEAN_NAME, mapping);
      request.setAttribute(VIEW_BEAN_NAME, view);
      List dtos = new ArrayList();
      UserUtils.setP(view, "groupList", dtos);
      boolean userAdmin = isUserInRole(visitor, "UserAdmin");
      if (!userAdmin) { // non user admin
        AccessManager accessMgr = AccessManager.instance();
        List orgAdmins = accessMgr.getOwnerObjectsForPrincipal((Principal)visitor, "OrganizationAdmin");
        if ((null != orgAdmins) && (orgAdmins.size() > 0)) { // org admin
          if ("root".equals(groupFQN)) {
            // first time: use the top level nodes
            for (Iterator it = orgAdmins.iterator(); it.hasNext(); ) {
              ACObjectID ac = (ACObjectID) it.next();
              ViewDynaBean oneDto = new ViewDynaBean(DTO_BEAN_NAME, mapping);
              UserUtils.setP(oneDto, "fqn", ac.getObjectID());
              // Not specific enough: UserUtils.setP(oneDto, "name", extractPathName(ac.getObjectID()));
              UserUtils.setP(oneDto, "name", ac.getObjectID());
              dtos.add(oneDto);
            }
            UserUtils.setP(view, "numOfGroups", new Long(orgAdmins.size()));
            UserUtils.setP(view, "groupName", getResources(request, "mt.messages").getMessage(getLocale(request), "mt.group.label.root"));
          }
          else {
            return prepareForANode(groupFQN, view, dtos, orgAdmins, mapping, form, request, serviceName);
          }
        }
        else {
          //request.setAttribute(Globals.ERROR_KEY, "error.group.noGroupAdmin");
          //return mapping.findForward("failure");
          //quietly return
        }
      }
      else { // user admin
        if ("root".equals(groupFQN)) {
          VisitorGroupManager vGroupMgr = null;
          List userGrpCxts = GroupContextParser.getUserGroupContextNames();
          if (null == userGrpCxts) {
            String defaultCxt = GroupContextParser.getDefaultNamingContextName();
            try {
              vGroupMgr = new VisitorGroupManager(defaultCxt);
              vGroupMgr.setServiceName(serviceName);
              if (!vGroupMgr.isRootContextValid()) {
                vGroupMgr.createRootContext();
              }
            }
            catch(Exception ex) {
              ex.printStackTrace();
              request.setAttribute(Globals.ERROR_KEY, "error.application");
              return mapping.findForward("failure");
            }
            VisitorGroup rootGroup = vGroupMgr.getRootVisitorGroup();
            if (!rootGroup.isActive()) {
              rootGroup.activate();
            }
            ViewDynaBean oneDto = new ViewDynaBean(DTO_BEAN_NAME, mapping);
            String gName = rootGroup.getName();
            int idx = gName.indexOf(":");
            if (idx > -1) {
              gName = gName.substring(idx + 1);
            }
            // Not specific enough: UserUtils.setP(oneDto, "name", this.getLastGroupName(gName));
            // UserUtils.setP(oneDto, "name", gName);
            // changes to support groups by service
            UserUtils.setP(oneDto, "name",serviceName);
            String FQN = rootGroup.getFullyQualifiedName(); 
            UserUtils.setP(oneDto, "fqn", FQN);
            String gpName = getPortalRootNameFromFQN(FQN);
            UserUtils.setP(view, "groupName", gpName); 
            dtos.add(oneDto);
            UserUtils.setP(view, "numOfGroups", new Long(1));
          }
          else {
            for (Iterator it = userGrpCxts.iterator(); it.hasNext();) {
              String grpCName = (String) it.next();
              try {
                vGroupMgr = new VisitorGroupManager(grpCName);
                vGroupMgr.setServiceName(serviceName);
                if (!vGroupMgr.isRootContextValid()) {
                  vGroupMgr.createRootContext();
                }
              }
              catch(Exception ex) {
                ex.printStackTrace();
                continue;
                //request.setAttribute(Globals.ERROR_KEY, "error.application");
                //return mapping.findForward("failure");
              }
              VisitorGroup rootGroup = vGroupMgr.getRootVisitorGroup();
              if (!rootGroup.isActive()) {
                rootGroup.activate();
              }
              ViewDynaBean oneDto = new ViewDynaBean(DTO_BEAN_NAME, mapping);
              String gName = rootGroup.getName();
              int idx = gName.indexOf(":");
              if (idx > -1) {
                gName = gName.substring(idx + 1);
              }
              // Not specific enough: UserUtils.setP(oneDto, "name", this.getLastGroupName(gName));
              UserUtils.setP(oneDto, "name", gName);
              // changes to support groups by service
              UserUtils.setP(oneDto, "name", serviceName);
              String FQN = rootGroup.getFullyQualifiedName();
              UserUtils.setP(oneDto, "fqn", FQN);
              String gpName = getPortalRootNameFromFQN(FQN); 
              UserUtils.setP(view, "groupName", gpName);   
              dtos.add(oneDto);
            }
            UserUtils.setP(view, "numOfGroups", new Long(userGrpCxts.size()));
          }
         // UserUtils.setP(view, "groupName", getResources(request, "mt.messages").getMessage(getLocale(request), "mt.group.label.root"));
        }
        else {
          return prepareForANode(groupFQN, view, dtos, null, mapping, form, request, serviceName);
        }
      }
    }
    catch (Exception ex) {
      request.setAttribute(Globals.ERROR_KEY, "error.application");
      return mapping.findForward("failure");
    }
    return mapping.findForward("success");
  }

  private ActionForward prepareForANode(String groupFQN,
					ViewDynaBean view,
					List dtos,
					List orgAdmins,
					ActionMapping mapping,
					ActionForm form,
					HttpServletRequest request,
					String serviceName)
    throws Exception
  {
    VisitorGroupManager vGroupMgr = null;
    try {
      int iEnd = groupFQN.indexOf(":");
      vGroupMgr = new VisitorGroupManager(groupFQN.substring(0,iEnd));
      vGroupMgr.setServiceName(serviceName);
      if (!vGroupMgr.isRootContextValid()) {
        vGroupMgr.createRootContext();
      }
    }
    catch(Exception ex) {
      ex.printStackTrace();
      request.setAttribute(Globals.ERROR_KEY, "error.application");
      return mapping.findForward("failure");
    }
    AccessManager aclMgr = AccessManager.instance();
    VisitorGroup thisGroup = VisitorGroupManager.getVisitorGroupByFqn(groupFQN);
//Not null check added to see whether object exists.
    if(thisGroup!=null){
    List subGroups = thisGroup.getSubGroups();
    if(subGroups!=null){
    for (int i = 0; i < subGroups.size(); i++){
      VisitorGroup vG = (VisitorGroup) subGroups.get(i);
      ViewDynaBean oneDto = new ViewDynaBean(DTO_BEAN_NAME, mapping);
      //UserUtils.setP(oneDto, "name", vG.getGroupName());
      UserUtils.setP(oneDto, "name", getLastGroupName(vG.getFriendlyName()));
      UserUtils.setP(oneDto, "fqn", vG.getFullyQualifiedName());
      OrganizationObjectInfo org = new OrganizationObjectInfo(vG);
      ArrayList admins = (ArrayList) aclMgr.getPrincipalsInRole("OrganizationAdmin", org);
      StringBuffer adminAliases = new StringBuffer();
      if (null != admins) {
        for (int j = 0; j < admins.size(); j++) {
          Visitor v = (Visitor) admins.get(j);
          adminAliases.append(v.getName());
          if (j < admins.size() - 1) {
            adminAliases.append(", ");
          }
        }
      }
      UserUtils.setP(oneDto, "admins", adminAliases.toString());
      dtos.add(oneDto);
    }}
    //UserUtils.setP(view, "groupName", thisGroup.getGroupName());
    UserUtils.setP(view, "groupName", getLastGroupName(thisGroup.getFriendlyName()));
    UserUtils.setP(view, "numOfGroups", new Long(subGroups.size()));
    // breadcrumb support
    HashMap orgAdminGroups = new HashMap();
    if (orgAdmins != null) {
      for (Iterator it = orgAdmins.iterator(); it.hasNext(); ) {
        ACObjectID ac = (ACObjectID)it.next();
        orgAdminGroups.put(ac.getObjectID(), ac);
      }
    }
    List parentGroupList = thisGroup.getParents(true);
    List theBreadcrumbs = new ArrayList();
    ViewDynaBean oneDto = new ViewDynaBean(DTO_BEAN_NAME, mapping);
    // UserUtils.setP(oneDto, "name", getResources(request, "mt.messages").getMessage(getLocale(request), "mt.group.label.root"));
    UserUtils.setP(oneDto, "name",getPortalRootName(thisGroup.getFriendlyName()));
    UserUtils.setP(oneDto, "fqn", "root");
    theBreadcrumbs.add(oneDto);
    if (parentGroupList != null && parentGroupList.isEmpty() == false) {
      boolean skipParent = true;
      for (int i = parentGroupList.size() - 1; i >= 0; i--) {
        VisitorGroup oneVisitorGroup = (VisitorGroup)parentGroupList.get(i);
        String onefqn = oneVisitorGroup.getFullyQualifiedName();
        oneDto = new ViewDynaBean(DTO_BEAN_NAME, mapping);

        // change made to support groups by service
        String groupName = this.getLastGroupName(oneVisitorGroup.getFriendlyName());
        String scriptRoot= getPortalRootNameFromFQN(onefqn);
        if (!(groupName.equals(scriptRoot))){
          UserUtils.setP(oneDto, "name", groupName);  
        }
        theBreadcrumbs.add(oneDto);
        if (skipParent == true && orgAdmins != null && orgAdminGroups.containsKey(onefqn) == false) {
          continue;
        }
        else {
          skipParent = false;
        }
        UserUtils.setP(oneDto, "fqn", oneVisitorGroup.getFullyQualifiedName());
      }
    }
    UserUtils.setP(view, "breadcrumbs", theBreadcrumbs);
    // get user members, not recursively
    List visitorList = thisGroup.getVisitors(false);
     List memberList = new ArrayList((visitorList == null) ? 0 : visitorList.size());
     UserUtils.setP(view, "memberList", memberList);
    if (null == visitorList) {
      return mapping.findForward("success");
    }
    // pagination support for users
    int countOfResults = visitorList.size();
    // entriesPerPage is always not null
    int entriesPerPage = ((Integer) UserUtils.getP(form, "entriesPerPage")).intValue();
    int firstEntry = 0;
    int lastEntry = countOfResults;
    int totalPageNumber = 1;
    int currentPageNumber = 1;
    if (countOfResults > entriesPerPage) {
      // currentPageNumber and totalPageNumber are always not null
      currentPageNumber = ((Integer) UserUtils.getP(form, "currentPageNumber")).intValue();
      totalPageNumber = countOfResults / entriesPerPage;
      if (countOfResults % entriesPerPage > 0) {
        totalPageNumber++;
      }
      // if the entriesPerPage has been increased
      if (currentPageNumber > totalPageNumber) {
        currentPageNumber = totalPageNumber;
      }
      if (currentPageNumber == 0) {
        // first page
        currentPageNumber = 1;
      }
      else {
        firstEntry = (currentPageNumber - 1) * entriesPerPage;
      }
      lastEntry = firstEntry + entriesPerPage;
    }
    else {
      entriesPerPage = countOfResults;
    }
    UserUtils.setP(form, "currentPageNumber", new Integer(currentPageNumber));
    UserUtils.setP(form, "totalPageNumber", new Integer(totalPageNumber));
    for (int i = firstEntry; (i < countOfResults) && (i < lastEntry); i++) {
      Visitor v = (Visitor) visitorList.get(i);
      //Added not null check
      if(v!=null){
      oneDto = new ViewDynaBean(DTO_MEMBER_BEAN_NAME, mapping);
      String formattedName = UserUtils.getFormattedName(v, getResources(request), getLocale(request));
      UserUtils.setP(oneDto, "name", formattedName);
      UserUtils.setP(oneDto, "userId", new Long(v.getId()));
      UserUtils.setP(oneDto, "userAlias", v.getName());
      UserUtils.setP(oneDto, "city", v.getStringValue("CITY"));
      UserUtils.setP(oneDto, "state", v.getStringValue("STATE"));
      UserUtils.setP(oneDto, "phone", v.getStringValue("BUS_PHONE"));
      UserUtils.setP(oneDto, "email", v.getStringValue("EMAIL"));
      memberList.add(oneDto);
  	}
    }}
    return mapping.findForward("success");
  }

  private String getLastGroupName(String name) {
    int i = name.lastIndexOf("/");
    if (i < 0) {
      return name;
    }
    else {
      return name.substring(i + 1);
    }
  }

   private String getPortalRootName(String name) {
    int i = name.lastIndexOf("/");
    if (i < 0) {
      return name;
    }
    else{
      StringTokenizer st = new StringTokenizer(name, "/");
      return st.nextToken();
    }
  } 

  private String getPortalRootNameFromFQN(String name) {
     int i = name.lastIndexOf("/");
     if (i < 0) {
       return name;
     }
     else{
       StringTokenizer st = new StringTokenizer(name, "/");
       st.nextToken();
       return st.nextToken();   
     }
  }
  /* This parseString function is never got used locally
  private List parseString(String str, String separator) {
    List list = new ArrayList();
    int currPos = 0;
    while ((null != str) && (str.indexOf(separator, currPos) > 0)) {
      int nextPos = str.indexOf(separator, currPos);
      list.add(str.substring(currPos, nextPos));
      currPos = nextPos + separator.length();
    }
    if ((currPos < str.length()) && (str.indexOf(separator, currPos) > 0)) {
      list.add(str.substring(currPos));
    }
    return list;
  }
  */

  private String extractPathName(String fqn) {
    int i = fqn.indexOf(":");
    if (i < 0) {
      return fqn;
    }
    else {
      return fqn.substring(i + 1);
    }
  }
}
